//*****************************************************************************
//
//								Monitor.c
//
//*****************************************************************************
//
//
#include <intrins.h>

#include "config.h"
#include "typedefs.h"
#include "reg.h"
#include "cpu.h"
#include "util.h"
#include "printf.h"
#include "i2c.h"
#include "monitor.h"
//#include "monitor_MCU.h"
//#include "monitor_SPI.h"
//#include "monitor_DDR.h"
//#include "monitor_OSD.h"
#include "main.h"

		BYTE 	DebugLevel = 0;
XDATA	BYTE	MonAddress = TW88I2CAddress;	
XDATA	BYTE	MonIndex;
XDATA	BYTE	MonRdata, MonWdata;
XDATA	BYTE	monstr[30];				// buffer for input string
XDATA	BYTE 	*argv[10];
XDATA	BYTE	argc=0;
		bit		echo=1;


CODE BYTE InitTest[] = {
	0x00, 0,
	#include "Data\Table_Video(INIT)_AT070TN83V3.txt"
	0xff,0xff,
};


/*
void SoftReset(void)
{
	BYTE page, dat;

	page = ReadTW88( 0xff );

	WriteTW88(0xff, 0);
	dat = ReadTW88(0x06);
	WriteTW88( 0x06, dat | 0x80 );
	WriteTW88( 0xff, page );
}
*/
//=============================================================================
//
//=============================================================================
void Prompt(void)
{
#ifdef INTERNAL_MCU
  #ifdef BANKING
	if ( MonAddress == TW88I2CAddress )
		Printf("\n[B%1x]MCU_I2C[%02bx]>", BANKREG, MonAddress);
	else
  #else
	if ( MonAddress == TW88I2CAddress )
		Printf("\nMCU_I2C[%02bx]>", MonAddress);
	else
  #endif
#endif
		Printf("\nI2C[%02bx]>", MonAddress);
}

void Mon_tx(BYTE ch)
{
	RS_tx(ch);
	//RS1_tx(ch);
}
//=============================================================================
//
//=============================================================================

void SetMonAddress(BYTE addr)
{
	MonAddress = addr;
}

void MonReadI2C(void)
{
	////////////////////////////////////
	BYTE len;
			
	if( argc>=2 ) for(len=0; len<10; len++) if( argv[1][len]==0 ) break;

	if( len>2 ) {
		MonWdata = a2h( argv[1] ) / 0x100;
		MonIndex = 0xff;

		Printf("\nWrite %02bxh:%02bxh ", MonIndex, MonWdata);
		if ( MonAddress == TW88I2CAddress ) {
			WriteTW88(MonIndex, MonWdata);
			MonRdata = ReadTW88(MonIndex);
		}
		else {
			WriteI2C(MonAddress, MonIndex, MonWdata);
			MonRdata = ReadI2C(MonAddress, MonIndex);
		}
   		Printf("==> Read %02bxh:%02bxh", MonIndex, MonRdata);
		if( MonWdata != MonRdata ) Printf(" [%02bx]", MonWdata);
	}
	////////////////////////////////////

	if( argc>=2 ) MonIndex = a2h( argv[1] );
	else	{
		Printf("   --> Missing parameter !!!");
		return;
	}

	if ( MonAddress == TW88I2CAddress )
		MonRdata = ReadTW88(MonIndex);
	else
		MonRdata = ReadI2C(MonAddress, MonIndex);

	if( echo )
		Printf("\nRead %02bxh:%02bxh", MonIndex, MonRdata);	
	
	MonWdata = MonRdata;
}


void MonWriteI2C(void) 
{
	////////////////////////////////////
	BYTE len;

	if( argc>=2 ) for(len=0; len<10; len++) if( argv[1][len]==0 ) break;

	if( len>2 ) {
		MonWdata = a2h( argv[1] ) / 0x100;
		MonIndex = 0xff;

		Printf("\nWrite %02bxh:%02bxh ", MonIndex, MonWdata);
		if ( MonAddress == TW88I2CAddress ) {
			WriteTW88(MonIndex, MonWdata);
			MonRdata = ReadTW88(MonIndex);
		}
		else {
			WriteI2C(MonAddress, MonIndex, MonWdata);
			MonRdata = ReadI2C(MonAddress, MonIndex);
		}
   		Printf("==> Read %02bxh:%02bxh", MonIndex, MonRdata);
		if( MonWdata != MonRdata ) Printf(" [%02bx]", MonWdata);
	}
	////////////////////////////////////

	if( argc<3 ) {
		Printf("   --> Missing parameter !!!");
		return;
	}
	
	MonIndex = a2h( argv[1] );
	MonWdata = a2h( argv[2] );
	
	if( echo ) {
		Printf("\nWrite %02bxh:%02bxh ", MonIndex, MonWdata);
		if ( MonAddress == TW88I2CAddress ) {
			WriteTW88(MonIndex, MonWdata);
			MonRdata = ReadTW88(MonIndex);
		}
		else {
			WriteI2C(MonAddress, MonIndex, MonWdata);
			MonRdata = ReadI2C(MonAddress, MonIndex);
		}
   		Printf("==> Read %02bxh:%02bxh", MonIndex, MonRdata);
		if( MonWdata != MonRdata ) Printf(" [%02bx]", MonWdata);
	}
	else {
		if ( MonAddress == TW88I2CAddress ) {
			WriteTW88(MonIndex, MonWdata);
		}
		else {
			WriteI2C(MonAddress, MonIndex, MonWdata);
		}
	}
}


void MonIncDecI2C(BYTE inc)
{
	switch(inc){
		case 0:  MonWdata--;	break;
		case 1:  MonWdata++;	break;
		case 10: MonWdata-=0x10;	break;
		case 11: MonWdata+=0x10;	break;
	}

	if ( MonAddress == TW88I2CAddress ) {
		WriteTW88(MonIndex, MonWdata);
		MonRdata = ReadTW88(MonIndex);
	}
	else {
		WriteI2C(MonAddress, MonIndex, MonWdata);
		MonRdata = ReadI2C(MonAddress, MonIndex);
	}

	if( echo ) {
		Printf("Write %02bxh:%02bxh ", MonIndex, MonWdata);
		Printf("==> Read %02bxh:%02bxh", MonIndex, MonRdata);
	}

	Prompt();

}

void MonDumpI2C(void)
{
	BYTE ToMonIndex;
	int  cnt=7;

	if( argc>=2 ) MonIndex   = a2h(argv[1]);
	if( argc>=3 ) ToMonIndex = a2h(argv[2]);
	else          ToMonIndex = MonIndex+cnt;
	
	if ( ToMonIndex < MonIndex ) ToMonIndex = 0xFF;
	cnt = ToMonIndex - MonIndex + 1;

	if( echo ) {
		if ( MonAddress == TW88I2CAddress ) {
			for ( ; cnt > 0; cnt-- ) {
				MonRdata = ReadTW88(MonIndex);
				Printf("\n==> Read %02bxh:%02bxh", MonIndex, MonRdata);
				MonIndex++;
			}
		}
		else {
			for ( ; cnt > 0; cnt-- ) {
				MonRdata = ReadI2C(MonAddress, MonIndex);
				Printf("\n==> Read %02bxh:%02bxh", MonIndex, MonRdata);
				if( MonWdata != MonRdata ) Printf(" [%02bx]", MonWdata);
				MonIndex++;
			}
		}
	}
	else {
		if ( MonAddress == TW88I2CAddress ) {
			for ( ; cnt > 0; cnt-- ) {
				MonRdata = ReadTW88(MonIndex);
				MonIndex++;
			}
		}
		else {
			for ( ; cnt > 0; cnt-- ) {
				MonRdata = ReadI2C(MonAddress, MonIndex);
				MonIndex++;
			}
		}
	}
}

//-----------------------------------------------------------------------------

void MonNewReadI2C(void)
{
	BYTE Slave;

	if( argc>=3 ) MonIndex = a2h( argv[2] );
	else	{
		Printf("   --> Missing parameter !!!");
		return;
	}
	Slave = a2h(argv[1]);

	if ( Slave == TW88I2CAddress )
		MonRdata = ReadTW88(MonIndex);
	else
		MonRdata = ReadI2C(Slave, MonIndex);

	if( echo )
		Printf("\n<R>%02bx[%02bx]=%02bx", Slave, MonIndex, MonRdata);
	
	MonWdata = MonRdata;
}

void MonNewWriteI2C(void)
{
	BYTE Slave;

	if( argc<4 ) {
		Printf("   --> Missing parameter !!!");
		return;
	}
	
	MonIndex = a2h( argv[2] );
	MonWdata = a2h( argv[3] );
	Slave    = a2h( argv[1] );
	
	if ( Slave == TW88I2CAddress ) {
		WriteTW88(MonIndex, MonWdata);
		MonRdata = ReadTW88(MonIndex);
	}
	else {
		WriteI2C(Slave, MonIndex, MonWdata);
		MonRdata = ReadI2C(Slave, MonIndex);
   	}
	if( echo ) {
//		_nop_ ();

		Printf("\n<R>%02bx[%02bx]=%02bx", Slave, MonIndex, MonRdata);
	}

}

void MonNewDumpI2C(void)
{
	BYTE 	ToMonIndex, Slave;
	WORD	i;
	
	if( argc>=2 ) MonIndex = a2h(argv[2]);
	if( argc>=3 ) ToMonIndex = a2h(argv[3]);
	Slave = a2h(argv[1]);

	if( echo ) {
		if ( Slave == TW88I2CAddress ) {
			for(i=MonIndex; i<=ToMonIndex; i++) {
				MonRdata = ReadTW88(i);
        		Printf("\n<R>%02bx[%02x]=%02bx", Slave, i, MonRdata);
			}
		}
		else {
			for(i=MonIndex; i<=ToMonIndex; i++) {
				MonRdata = ReadI2C(Slave, i);
        		Printf("\n<R>%02bx[%02x]=%02bx", Slave, i, MonRdata);
			}
		}
	}
	else {
		if ( Slave == TW88I2CAddress ) {
			for(i=MonIndex; i<=ToMonIndex; i++) {
				MonRdata = ReadTW88(i);
			}
		}
		else {
			for(i=MonIndex; i<=ToMonIndex; i++) {
				MonRdata = ReadI2C(Slave, i);
			}
		}
	}
}


void MonWriteBit(void)
{
	BYTE mask, i, FromBit, ToBit,  MonMask, val;
	BYTE Slave;
	// b 88 index startbit|endbit data

	if( argc<5 ) {
		Printf("   --> Missing parameter !!!");
		return;
	}
	Slave = a2h(argv[1]);

	MonIndex = a2h( argv[2] );
	FromBit  = (a2h( argv[3] ) >> 4) & 0x0f;
	ToBit  = a2h( argv[3] )  & 0x0f;
	MonMask  = a2h( argv[4] );

	if( FromBit<ToBit || FromBit>7 || ToBit>7) {
		Printf("\n   --> Wrong range of bit operation !!!");
		return;
	}
	
	mask = 0xff; 
	val=0x7f;
	for(i=7; i>FromBit; i--) {
		mask &= val;
		val = val>>1;
	}

	val=0xfe;
	for(i=0; i<ToBit; i++) {
		mask &= val;
		val = val<<1;
	}

	if ( Slave == TW88I2CAddress ) {
		MonRdata = ReadTW88(MonIndex);
		MonWdata = (MonRdata & (~mask)) | (MonMask & mask);
				
		WriteTW88(MonIndex, MonWdata);
		MonRdata = ReadTW88(MonIndex);
	}
	else {
		MonRdata = ReadI2C(Slave, MonIndex);
		MonWdata = (MonRdata & (~mask)) | (MonMask & mask);
				
		WriteI2C(Slave, MonIndex, MonWdata);
		MonRdata = ReadI2C(Slave, MonIndex);
	}

	if( echo )
		Printf("\n<R>%02bx[%02bx]=%02bx", Slave, MonIndex, MonRdata);

}

//=============================================================================
//			Help Message
//=============================================================================
void MonHelp(void)
{

	Puts("\n=======================================================");
	Puts("\n>>>     Welcome to Techwell Monitor  Rev 1.00     <<<");
	Puts("\n=======================================================");
	Puts("\n   R ii             ; Read data");
	Puts("\n   W ii dd          ; Write data");
	Puts("\n   D [ii] [cc]      ; Dump");
	Puts("\n   C aa             ; Change I2C address");
	Puts("\n   Echo On/Off      ; Terminal Echoing On/Off");
	Puts("\n");
	Puts("\n=======================================================");
	Puts("\n");

}

//=============================================================================
//
//=============================================================================
BYTE MonGetCommand(void)
{
	static BYTE comment=0;
	static BYTE incnt=0, last_argc=0;
	BYTE i, ch;
	BYTE ret=0;

	if( !RS_ready() ) return 0;
	ch = RS_rx();

	//----- if comment, echo back and ignore -----
	if( comment ) {
		if( ch=='\r' || ch==0x1b ) comment = 0;
		else { 
			Mon_tx(ch);
			return 0;
		}
	}
	else if( ch==';' ) {
		comment = 1;
		Mon_tx(ch);
		return 0;
	}

	//=====================================
	switch( ch ) {

	case 0x1b:
		argc = 0;
		incnt = 0;
		comment = 0;
		Prompt();
		return 0;

	//--- end of string
	case '\r':

		if( incnt==0 ) {
			Prompt();
			break;
		}

		monstr[incnt++] = '\0';
		argc=0;

		for(i=0; i<incnt; i++) if( monstr[i] > ' ' ) break;

		if( !monstr[i] ) {
			incnt = 0;
			comment = 0;
			Prompt();
			return 0;
		}
		argv[0] = &monstr[i];
		for(; i<incnt; i++) {
			if( monstr[i] <= ' ' ) {
				monstr[i]='\0';
     			 //Printf("(%s) ",  argv[argc]);
				i++;
				while( monstr[i]==' ' ) i++;
				argc++;
				if( monstr[i] ){
     			 argv[argc] = &monstr[i];
				}
			}
		}

		ret = 1;
		last_argc = argc;
		incnt = 0;
		
		break;

	//--- repeat command
	case '/':
		argc = last_argc;
		ret = 1;
		break;

	//--- repeat command without CR
	case '`':
	{
		BYTE i, j, ch;

		for(j=0; j<last_argc; j++) {
			for(i=0; i<100; i++) {
				ch = argv[j][i];
				if( ch==0 ) {
					if( j==last_argc-1 ) return 0;
					ch = ' ';
					RS_ungetch( ch );
					break;
				}
				else {
					RS_ungetch( ch );
				}
			}
		}
		break;
	}

	//--- back space
	case 0x08:
		if( incnt ) {
			incnt--;
			Mon_tx(ch);
			Mon_tx(' ');
			Mon_tx(ch);
		}
		break;

	//--- decreamental write
	case ',':
		if( incnt ) {
			Mon_tx(ch);
			monstr[incnt++] = ch;
		}
		else
			MonIncDecI2C(0);
		break;

	case '<':
		if( incnt ) {
			Mon_tx(ch);
			monstr[incnt++] = ch;
		}
		else
			MonIncDecI2C(10);
		break;

	//--- increamental write
	case '.':
		if( incnt ) {
			Mon_tx(ch);
			monstr[incnt++] = ch;
		}
		else
			MonIncDecI2C(1);
		break;

	case '>':
		if( incnt ) {
			Mon_tx(ch);
			monstr[incnt++] = ch;
		}
		else
			MonIncDecI2C(11);
		break;

	default:
		Mon_tx(ch);
		monstr[incnt++] = ch;
		break;
	}

	if( ret ) {
		comment = 0;
		last_argc = argc;
		return ret;
	}
	else {
		return ret;
	}
}

//*****************************************************************************
//				Monitoring Command
//*****************************************************************************
extern DATA BYTE RS_buf[];
extern DATA BYTE RS_in, RS_out;

BYTE *MonString = 0;

void Monitor(void)
{
	if( MonString ) {
		RS_ungetch( *MonString++ );
		if( *MonString==0 ) MonString = 0;
	}

	if( !MonGetCommand() ) return;

	if( !stricmp( argv[0], "1" ) ) {
		MonString = "\rinit \rosd 0 \rosd 1 \rosd pigeonl\r";
		return;
	}

	if( !stricmp( argv[0], "OSDTEST" ) ) {
		MonString = "\rinit \rosd 0 \rosd 1 \rosd pigeonl\rosd rose \rosd harry \rosd exp16 \rosd LUT16 \r";
		return;
	}

	if( !stricmp( argv[0], "2" ) ) {
		MonString = "\rw 82 02\rosd 1 0 0 1024 1024 0\rosd pigeonl\r";
		return;
	}

	//---------------- Write Register -------------------
	if( !stricmp( argv[0], "W" ) ) {
		MonWriteI2C();
	}
	else if( !stricmp( argv[0], ")" ) ) {
		MonNewWriteI2C();
	}
	//---------------- Read Register --------------------
	else if ( !stricmp( argv[0], "R" ) ) {
		MonReadI2C();
	}
	else if ( !stricmp( argv[0], "(" ) ) {
		MonNewReadI2C();
	}
	//---------------- Dump Register --------------------
	else if( !stricmp( argv[0], "D" ) ) {
		Puts("\ndump start");
		MonDumpI2C();
	}
	else if( !stricmp( argv[0], "&" ) ) {
		MonNewDumpI2C();
	}

	//---------------- Bit Operation --------------------
	else if( !stricmp( argv[0], "B" ) ) {// Write bits - B AA II bb DD
		MonWriteBit();
	}
	//---------------- Change I2C -----------------------
	else if( !stricmp( argv[0], "C" ) ) {
		MonAddress = a2h( argv[1] );
	}

	//---------------- Help -----------------------------
	else if( !stricmp( argv[0], "H" ) || !stricmp( argv[0], "HELP" ) || !stricmp( argv[0], "?" ) ) {
		MonHelp();

	}
	//---------------------------------------------------
	else if( !stricmp( argv[0], "*" ) ) {
			
				if( argc==1 ) {
					Printf("\n  * 0 : Program default Loader");
					Printf("\n  * 1 : Program external Loader");
					Printf("\n  * 2 : Execute Loader");
				}
				else { 
					BYTE mode;
					mode = a2h(argv[1]);
					//Loader(mode);
				}
	}

	//---------------- Debug Level ---------------------
	else if ( !stricmp( argv[0], "DEBUG" ) ) {
		if( argc==2 ) {
			DebugLevel = a2h(argv[1]);
		}
		Printf("\nDebug Level = %2bx", DebugLevel);
	}
	
	//---------------- Echo back on/off -----------------
	else if ( !stricmp( argv[0], "echo" ) ) {
		if( !stricmp( argv[1], "off" ) ) {
			echo = 0;
			Printf("\necho off");
		}
		else {
			echo = 1;
			Printf("\necho on");
		}
	}
	//---------------- MCU Reboot ----------------------
	else if ( !stricmp( argv[0], "reboot" ) ) {
		if( (argc==2) && (!stricmp( argv[1], "ISP") ) ) {
			WriteTW88( 0xff, MCU_PAGE );
			WriteTW88( 0x21, 0x55 );
			WriteTW88( 0x21, 0xaa );
			WriteTW88( 0x20, 0x8b );	// reboot with ISP-ROM
		}			
		else if( (argc==2) && (!stricmp(argv[1], "SPI") ) ) {
			WriteTW88( 0xff, MCU_PAGE );
			WriteTW88( 0x21, 0x55 );
			WriteTW88( 0x21, 0xaa );
			WriteTW88( 0x20, 0x8a );	// reboot with SPI-Flash
		}
		else {
			Printf("\nType reboot ISP/SPI\n");
		}
	}
	//---------------- Init Test -------------------------
	else if( !stricmp( argv[0], "INIT" ) ) {
		Printf("\nInitialize...");
		I2CDeviceInitialize(InitTest);
		WriteI2C(0x88, 0x1f, 0x01);		// FPGA decoder ADC test mode

	}
	//---------------- OSD Test --------------------------
	else if( !stricmp( argv[0], "OSD" ) ) {
		//MonitorOSD(PIXEL8);
	}
	//---------------- OSD Test --------------------------
	else if( !stricmp( argv[0], "OSD16" ) ) {
		//MonitorOSD(PIXEL16);
	}
	//---------------- MCU Debug -------------------------
	else if( !stricmp( argv[0], "MCU" ) ) {
		MonitorMCU();
	}
	
	//---------------- SPI Debug -------------------------
	else if( !stricmp( argv[0], "SPI" ) ) {
		MonitorSPI();
	}
	
	else if( !stricmp( argv[0], "EE" ) ) {
		MonitorEE();
	}
	
	//---------------- DDR Debug -------------------------
	else if( argv[0][0]=='D' || argv[0][0]=='d' ) {
		MonDDR();
	}
	
	//----------------------------------------------------
	else {
		Printf("\nInvalid command...");
	}


	Prompt();


}


/*void Monitor1(void)
{
BYTE	ch;

	if( !RS1_ready() ) return;
	ch = RS1_rx();					// get data
	RS1_tx(ch);		   				// echo back
}*/
//-------------------------------------------------------------------------






